/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package snail.data;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Criterion;
import snail.hibernate.util.HibernateUtil;

/**
 *
 * @author Mickel
 */
public class GenericHibernateDAO<T, ID extends Serializable> implements IGenericDAO<T, ID> {

    private Class<T> persistentClass;
    private Session session;

    public GenericHibernateDAO() {
        this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    // <editor-fold defaultstate="collapsed" desc="Session and Persistent getters & setters">
    @SuppressWarnings("unchecked")
    public void setSession(Session session) {
        this.session = session;
    }

    protected Session getSession() {
        if (session == null) {
            session = HibernateUtil.getSessionFactory().getCurrentSession();
            session.beginTransaction();
        }

        return session;
    }

    public Class<T> getPersistentClass() {
        return persistentClass;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Entity getters">
    public T getById(ID id) {
        return (T) getSession().load(getPersistentClass(), id);
    }

    public List<T> getAll() {
        return getByCriteria();
    }

    @SuppressWarnings("unchecked")
    public List<T> getByExample(T exampleInstance, String[] excludeProperty) {
        Criteria crit = getSession().createCriteria(getPersistentClass());
        Example example = Example.create(exampleInstance);
        for (String exclude : excludeProperty) {
            example.excludeProperty(exclude);
        }
        crit.add(example);
        return crit.list();
    }

    @SuppressWarnings("unchecked")
    protected List<T> getByCriteria(Criterion... criterion) {
        Criteria crit = getSession().createCriteria(getPersistentClass());
        for (Criterion c : criterion) {
            crit.add(c);
        }
        return crit.list();
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Hibernate session-specific methods">
    @SuppressWarnings("unchecked")
    public T makePersistent(T entity) {
        getSession().saveOrUpdate(entity);
        return entity;
    }

    public void makeTransient(T entity) {
        getSession().delete(entity);
    }

    public void flush() {
        getSession().flush();
    }

    public void clear() {
        getSession().clear();
    }
    // </editor-fold>
}
